package com.diamondsys.embrapa;

import com.diamondsys.embrapa.util.JsfUtil;
import com.diamondsys.embrapa.util.JsfUtil.PersistAction;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import java.io.IOException;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author Rafael
 */
@Named("tbInstController")
@SessionScoped
public class TbInstController implements Serializable {
    @EJB
    private com.diamondsys.embrapa.TbInstFacade ejbFacade;
    private List<TbInst> items = null;
    private List<TbInst> itemsEvento = null;
    private TbInst selected;
    private List<String> selectedInteresses = null;
    private SigifEventosint selectedEvento;
    private Categoria cat = null;
    
    //Filtro Data Inclusão
    private Date dateFrom;
    private Date dateTo;

    public Date getDateFrom() {
        return dateFrom;
    }

    public void setDateFrom(Date dateFrom) {
        this.dateFrom = dateFrom;
    }

    public Date getDateTo() {
        return dateTo;
    }

    public void setDateTo(Date dateTo) {
        this.dateTo = dateTo;
    }
    
    public boolean filterByDate(Object value, Object filter, Locale locale) {
        boolean ret=true;
        
        String filterText = (value == null) ? null : value.toString().trim();
        if (filterText == null || filterText.isEmpty()) {
            return true;
        }
        
        DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        Date filterDate;

        try {
            filterDate = df.parse(filterText);

            if (dateFrom != null && dateFrom.after(filterDate)) ret = false;
            if (dateTo != null && dateTo.before(filterDate)) ret = false;

        } catch (ParseException e) {
            return true;
        }

       return ret;
    } 

    //Filtro Data Nascimento/Fundação
    private Date dateFromNascimento;
    private Date dateToNascimento;

    public Date getDateFromNascimento() {
        return dateFromNascimento;
    }

    public void setDateFromNascimento(Date dateFromNascimento) {
        this.dateFromNascimento = dateFromNascimento;
    }

    public Date getDateToNascimento() {
        return dateToNascimento;
    }

    public void setDateToNascimento(Date dateToNascimento) {
        this.dateToNascimento = dateToNascimento;
    }
    
    public boolean filterByDateNascimento(Object value, Object filter, Locale locale) {
        boolean ret=true;
        
        String filterText = (value == null) ? null : value.toString().trim();
        if (filterText == null || filterText.isEmpty()) {
            return true;
        }
        
        DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        Date filterDate;

        try {
            filterDate = df.parse(filterText);

            if (dateFromNascimento != null && dateFromNascimento.after(filterDate)) ret = false;
            if (dateToNascimento != null && dateToNascimento.before(filterDate)) ret = false;

        } catch (ParseException e) {
            return true;
        }

       return ret;
    } 

    /**
     *
     */
    public TbInstController() {
        
    }

    /**
     *
     * @return
     */
    
    public TbInst getSelected() {
        if(selected != null)selected.setDesSenha(" ");
        return selected;
    }

    /**
     *
     * @param selected
     */
    public void setSelected(TbInst selected) {
        if (selected != null)
        {
            this.selected = selected;
            InteressesController interessesController = (InteressesController) FacesContext.getCurrentInstance().getApplication().getELResolver().
                    getValue(FacesContext.getCurrentInstance().getELContext(), null, "interessesController");

            this.selected.setInteressesList(interessesController.findByClienteId(selected));
            
            this.selectedInteresses = new ArrayList<String>();
            for (Interesses item : this.selected.getInteressesList()) {
                this.selectedInteresses.add(item.getId().toString());
            }
            if(selected.getSubcategoriaId() == null || selected.getSubcategoriaId().getCategoriaId().getId() == 0) cat = null;
            else cat = selected.getSubcategoriaId().getCategoriaId();
            
            this.selected.setDesSenha(" ");
        }
    }

    /**
     *
     */
    protected void setEmbeddableKeys() {
    }

    /**
     *
     */
    protected void initializeEmbeddableKey() {
    }

    private TbInstFacade getFacade() {
        return ejbFacade;
    }

    /**
     *
     * @return
     */
    public TbInst prepareCreate() {
        selected = new TbInst();
        cat = null;
        setSelectedInteresses(new ArrayList<String>());
        selected.setInteressesList(new ArrayList<Interesses>());
        selected.setDatInclusao(new Date());
        selected.setDesInclusao(((Usuario)JsfUtil.GetSessionParameter("user")).getLogin());
        initializeEmbeddableKey();
        return selected;
    }

    /**
     *
     * @return
     */
    public TbInst prepareCreateCliente() {
        selected = new TbInst();
        setSelectedInteresses(new ArrayList<String>());
        selected.setInteressesList(new ArrayList<Interesses>());
        selected.setDatInclusao(new Date());
        initializeEmbeddableKey();
        selected.setDesLideranca("N");
        selected.setDesSenha("");
        
        return selected;
    }
    
    /**
     *
     */
    public void create() {
        persist(PersistAction.CREATE, ResourceBundle.getBundle("/Bundle").getString("TbInstCreated"));
        if (!JsfUtil.isValidationFailed()) {
            items = null;    // Invalidate list of items to trigger re-query.
        }
    }

    /**
     *
     */
    public void update() {
        persist(PersistAction.UPDATE, ResourceBundle.getBundle("/Bundle").getString("TbInstUpdated"));
    }

    /**
     *
     * @throws java.io.IOException
     */
    public void updateCliente() throws IOException {
        persist(PersistAction.UPDATE, ResourceBundle.getBundle("/Bundle").getString("TbInstUpdated"));
        JsfUtil.AddSessionParameter("cliente", null);

        String uri = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRequestURI();
        String fileName = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getPathInfo();

        FacesContext.getCurrentInstance().getExternalContext().redirect(uri.replace(fileName, "/login/LoginCliente.xhtml"));        
        
    }
    
    /**
     *
     */
    public void destroy() {
        persist(PersistAction.DELETE, ResourceBundle.getBundle("/Bundle").getString("TbInstDeleted"));
        if (!JsfUtil.isValidationFailed()) {
            selected = null; // Remove selection
            items = null;    // Invalidate list of items to trigger re-query.
        }
    }

    /**
     *
     * @return
     */
    public List<TbInst> getItems() {
        if (items == null) {
            VisitasController visitasController = (VisitasController) FacesContext.getCurrentInstance().getApplication().getELResolver().
                    getValue(FacesContext.getCurrentInstance().getELContext(), null, "visitasController");
    
            items = getFacade().findAll();
            
            for(TbInst item: items)
            {
                item.setVisitasList(visitasController.findAbertasByClienteId(item));
            }
        }
        return items;
    }

    public boolean filterByInteresse(Object value, Object filter, Locale locale) {
        String filterText = (filter == null) ? null : filter.toString().trim();
        if(filterText == null||filterText.equals("")) {
            return true;
        }
         
        if(value == null) {
            return false;
        }
        
        for(Interesses item: (List<Interesses>)value)
        {
            if (item.getDescricao().toLowerCase().contains(filterText)) return true;
        }
         
        return false;
    }
    
    public String customFormatDate(Date date) {
        return JsfUtil.customFormatDate(date);
    }

    public void ClearItems() {
        items = null;
    }
    
    /**
     *
     * @param login
     * @return
     */
    public List<TbInst> findWithEmail(String login) {
        
        return getFacade().getEntityManager().createNamedQuery("TbInst.findByDesEmail", TbInst.class)
                .setParameter("desEmail", login)
                .getResultList();
    }
    
        /**
     *
     * @param login
     * @return
     */
    public TbInst getByEmail(String login) {
        
        try
        {
            return getFacade().getEntityManager().createNamedQuery("TbInst.findByDesEmail", TbInst.class)
                    .setParameter("desEmail", login)
                    .getSingleResult();
        }
        catch(Exception ex)
        {
            return null;
        }
    }
    /**
     * @return the cat
     */
    public Categoria getCat() {

        return cat;
    }    
    
    private void persist(PersistAction persistAction, String successMessage) {
        if (selected != null) {
            setEmbeddableKeys();
            
            InteressesController interessesController = (InteressesController) FacesContext.getCurrentInstance().getApplication().getELResolver().
                    getValue(FacesContext.getCurrentInstance().getELContext(), null, "interessesController");
            try {
                if (persistAction != PersistAction.DELETE) {
                    
                    if (!selected.getDesEmail().contains("@") || !selected.getDesEmail().split("@")[1].contains(".")){
                        JsfUtil.addWarningMessage("Formato de email inválido!");
                        JsfUtil.setValidationFailed();
                        return;
                    }
                    
                    if (selected.getDesCnpjCpf() != null && !JsfUtil.isValidCNPJ(selected.getDesCnpjCpf()) && !JsfUtil.isValidCPF(selected.getDesCnpjCpf())){
                        JsfUtil.addWarningMessage("O CPF/CNPJ informado é inválido!");
                        JsfUtil.setValidationFailed();
                        return;
                    }      

                    TbInst clienteExistente = getByEmail(selected.getDesEmail());
                    
                    if ( clienteExistente != null &&
                         ((persistAction == PersistAction.CREATE) ||
                          (persistAction == PersistAction.UPDATE && !clienteExistente.getCodInstituicao().equals(selected.getCodInstituicao()))))
                    {
                        JsfUtil.addWarningMessage("O email informado já está em uso!");
                        JsfUtil.setValidationFailed();
                        return;
                    }
                    if (persistAction == PersistAction.UPDATE && clienteExistente == null)
                    {
                        clienteExistente = this.getTbInst(selected.getCodInstituicao());
                    }
                    
                    
                    String senha="";
                    if (persistAction == PersistAction.UPDATE && (selected.getDesSenha() == null || selected.getDesSenha().trim().isEmpty()))
                    {
                        selected.setDesSenha(clienteExistente.getDesSenha());
                    }
                    else if (persistAction == PersistAction.CREATE && (selected.getDesSenha() == null || selected.getDesSenha().trim().isEmpty()) )
                    {
                        senha = UUID.randomUUID().toString().split("-")[0];
                        selected.setDesSenha(JsfUtil.encryptMD5(senha));
                    }
                    else
                    {
                        senha = selected.getDesSenha();
                        selected.setDesSenha(JsfUtil.encryptMD5(selected.getDesSenha()));
                    }
                    
                    
                    
                    List<Interesses> clienteInteresses = interessesController.findByClienteId(selected);

                    selected.setInteressesList(new ArrayList<Interesses>());
                    
                    selected.setDatAtualiz(new Date());
                    
                    if (((Usuario)JsfUtil.GetSessionParameter("user")) != null)
                        selected.setDesAlteracao(((Usuario)JsfUtil.GetSessionParameter("user")).getLogin());
                    else
                        selected.setDesAlteracao("criado por cliente");
                        
                    getFacade().edit(selected);

                    interessesController.setSelected(new Interesses());
                    
                    this.selected = getByEmail(selected.getDesEmail());

                    for(Interesses item: clienteInteresses)
                    {
                        if(!selectedInteresses.contains(item.getId().toString()))
                        { 
                            interessesController.removeRelationItem(item.getId(), selected.getCodInstituicao());
                        }
                        else
                        {
                            selectedInteresses.remove(item.getId().toString());
                        }
                    }

                    for(String item: selectedInteresses)
                    {
                        interessesController.addRelationItem(Integer.parseInt(item), selected.getCodInstituicao());
                    }
                    
                    if (persistAction == PersistAction.CREATE)
                    {
                        JsfUtil.sendEmailUsuarioNovo(selected.getDesEmail(), selected.getNomFantasia(), senha);
                    }
                    
                } else {
                    getFacade().remove(selected);
                }
                JsfUtil.addSuccessMessage(successMessage);
            } catch (EJBException ex) {
                String msg = "";
                Throwable cause = ex.getCause();
                JsfUtil.setValidationFailed();
                if (cause != null) {
                    msg = cause.getLocalizedMessage();
                }
                if (msg.length() > 0) {
                    JsfUtil.addErrorMessage(msg);
                } else {
                    JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
                }
            } catch (Exception ex) {
                Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
                JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            }
        }
    }

    /**
     *
     * @throws IOException
     */
    public void LoginCliente() throws IOException {
   
        List<TbInst> usuarios = this.findWithEmail(selected.getDesEmail());
        
        if ( usuarios != null && !usuarios.isEmpty() && usuarios.get(0).getDesSenha().equals(JsfUtil.encryptMD5(selected.getDesSenha())))
        {
            this.setSelected(usuarios.get(0));
            JsfUtil.AddSessionParameter("cliente", this.selected);
            
            String uri = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRequestURI();
            String fileName = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getPathInfo();
            
            FacesContext.getCurrentInstance().getExternalContext().redirect(uri.replace(fileName, "/tbInst/CreateCliente.xhtml"));
        }
        else
        {
            JsfUtil.addSuccessMessage("Usuário ou senha inválido");
        }
    }    
    
    public void RecuperarSenha() throws IOException {
   
        List<TbInst> usuarios = this.findWithEmail(selected.getDesEmail());
        
        if ( usuarios != null && !usuarios.isEmpty())
        {
            
            String senha = UUID.randomUUID().toString().split("-")[0];
            this.setSelected(usuarios.get(0));
            selected.setDesSenha(JsfUtil.encryptMD5(senha));
            getFacade().edit(selected);
            
            JsfUtil.sendEmailUsuarioNovo(selected.getDesEmail(), selected.getNomFantasia(), senha);
            
            selected = null;
            
            JsfUtil.addSuccessMessage("Uma nova senha foi enviada por email!");
        }
        else
        {
            JsfUtil.addWarningMessage("O email informado não consta em nossos registros!");
            JsfUtil.setValidationFailed();
            return;
        }
    }   
    
    
    public void FecharCliente() throws IOException {
   
        this.selected = null;
        JsfUtil.AddSessionParameter("cliente", null);

        String uri = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRequestURI();
        String fileName = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getPathInfo();

        FacesContext.getCurrentInstance().getExternalContext().redirect(uri.replace(fileName, "/login/LoginCliente.xhtml"));
    }    
    
    
    /**
     *
     * @param id
     * @return
     */
    public TbInst getTbInst(java.lang.Integer id) {
        return getFacade().find(id);
    }

    /**
     *
     * @return
     */
    public List<TbInst> getItemsAvailableSelectMany() {
        return getFacade().findAll();
    }

    /**
     *
     * @return
     */
    public List<TbInst> getItemsAvailableSelectOne() {
        return getFacade().findAll();
    }

    /**
     *
     */
    public List<TbInst> getClienteAniversariante() {
        return getFacade().getEntityManager().createQuery("select t from TbInst t where date_format(datNascimentoFundacao, '%m-%d')= date_format(curdate(), '%m-%d')", TbInst.class).getResultList();
    }

    /**
     *
     */
    public List<TbInst> getClienteNovo() {
        return getFacade().getEntityManager().createQuery("select t from TbInst t where date_format(datInclusao, '%Y-%m-%d')= curdate()", TbInst.class).getResultList();
    }

    /**
     * @return the selectedInteresses
     */
    public List<String> getSelectedInteresses() {
        return selectedInteresses;
    }

    /**
     * @param selectedInteresses the selectedInteresses to set
     */
    public void setSelectedInteresses(List<String> selectedInteresses) {
        this.selectedInteresses = selectedInteresses;
    }

    public void deletaEventoParcipantes() {
        try
        {
            if (this.selectedEvento != null)
            {
                this.getFacade().deletaParticipantesEvento(selectedEvento.getIdeventosint());
                this.itemsEvento.clear();
            }
        }
        catch(Exception ex)
        {
        }
    }    
    
    
    /**
     * @return the itemsEvento
     */
    public List<TbInst> getItemsEvento() {

        try
        {
            if (getSelectedEvento() != null) {
                itemsEvento = getFacade().findByeventId(getSelectedEvento().getIdeventosint());
            }
        }
        catch(Exception ex)
        {
        }
        if (itemsEvento == null) itemsEvento = new ArrayList<>();
       
        return itemsEvento;
    }

    /**
     * @param itemsEvento the itemsEvento to set
     */
    public void setItemsEvento(List<TbInst> itemsEvento) {
        this.itemsEvento = itemsEvento;
    }

    /**
     * @return the selectedEvento
     */
    public SigifEventosint getSelectedEvento() {
        return selectedEvento;
    }

    /**
     * @param selectedEvento the selectedEvento to set
     */
    public void setSelectedEvento(SigifEventosint selectedEvento) {
        this.selectedEvento = selectedEvento;
    }

    /**
     * @param cat the cat to set
     */
    public void setCat(Categoria cat) {
        if (cat == null || cat.getId() ==0) selected.setSubcategoriaId(null);
        this.cat = cat;
    }

    public void preProcessPDF(Object document) throws IOException, BadElementException, DocumentException {
 
        Document pdf = (Document) document;
        pdf.setPageSize(PageSize.A4.rotate());
        pdf.setMargins((float)-6, (float)-6, (float)0, (float)0);
        pdf.resetFooter();
        pdf.resetHeader();
        pdf.open();
    }    
    
    /**
     *
     */
    @FacesConverter(forClass = TbInst.class)
    public static class TbInstControllerConverter implements Converter {

        /**
         *
         * @param facesContext
         * @param component
         * @param value
         * @return
         */
        @Override
        public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
            if (value == null || value.length() == 0) {
                return null;
            }
            TbInstController controller = (TbInstController) facesContext.getApplication().getELResolver().
                    getValue(facesContext.getELContext(), null, "tbInstController");
            return controller.getTbInst(getKey(value));
        }

        java.lang.Integer getKey(String value) {
            java.lang.Integer key;
            key = Integer.valueOf(value);
            return key;
        }

        String getStringKey(java.lang.Integer value) {
            StringBuilder sb = new StringBuilder();
            sb.append(value);
            return sb.toString();
        }

        /**
         *
         * @param facesContext
         * @param component
         * @param object
         * @return
         */
        @Override
        public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
            if (object == null) {
                return null;
            }
            if (object instanceof TbInst) {
                TbInst o = (TbInst) object;
                return getStringKey(o.getCodInstituicao());
            } else {
                Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "object {0} is of type {1}; expected type: {2}", new Object[]{object, object.getClass().getName(), TbInst.class.getName()});
                return null;
            }
        }

    }

}
